package JUC.printWhen5;


import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @className: CountdownLatchArrayList
 * @Description:
 * @Author: wangyifei
 * @Date: 2022/9/4 14:59
 */
public class CountdownLatchArrayList {
    List<Integer> list = new ArrayList<>();
    public void add(Integer i){
        list.add(i);
    }
    public int size(){
        return list.size();
    }
    public static void main(String[] args) throws IOException {
        CountDownLatch t1Waitt2 = null ;//new CountDownLatch(1);
        CountDownLatch t2Waitt1 = null ;// new CountDownLatch(1);
        CountdownLatchArrayList list = null ; //new CountdownLatchArrayList();
        ThreadPoolExecutor pool = null ;
        Thread1 t1 = new Thread1(list , t1Waitt2 , t2Waitt1);
        Thread2 t2 = new Thread2(list , t1Waitt2 , t2Waitt1);
        for (int i = 0 ; i < 1000000 ; i++) {
//           pool =  new ThreadPoolExecutor(2 , 2 , 1000
//                   , TimeUnit.SECONDS
//                   , new ArrayBlockingQueue<Runnable>(19));
           list = new CountdownLatchArrayList();
           t1Waitt2 = new CountDownLatch(1);
           t2Waitt1 = new CountDownLatch(1);
           t1.setT1Waitt2(t1Waitt2);
           t1.setT2Waitt1(t2Waitt1);
           t2.setT2Waitt1(t2Waitt1);
           t2.setT1Waitt2(t1Waitt2);
           t1.setList(list);
           t2.setList(list);
           Thread tt = new Thread(t1);
           Thread ttt = new Thread(t2);
           ttt.start();
           tt.start();
            try {
                tt.join();
                ttt.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    public static class Thread2 extends Abs {

        public Thread2(CountdownLatchArrayList list, CountDownLatch t1Waitt2, CountDownLatch t2Waitt1) {
            super(list, t1Waitt2, t2Waitt1);
        }

        @Override
        public void run() {
            try {
                t1Waitt2.await();
                if(list.size() != 4){
                System.out.println("size is " + list.size());
                }
                t2Waitt1.countDown();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    public static class Thread1 extends Abs{

        public Thread1(CountdownLatchArrayList list, CountDownLatch t1Waitt2, CountDownLatch t2Waitt1) {
            super(list, t1Waitt2, t2Waitt1);
        }

        @Override
        public void run() {
            for(int i = 0 ; i < 10 ; i++){
                list.add(i);
//                System.out.println("put " + i);
                if(list.size() == 4){
                    t1Waitt2.countDown();
                    try {
                        t2Waitt1.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

            }
        }
    }

    public static abstract class Abs implements Runnable{
        protected CountdownLatchArrayList list ;
        protected CountDownLatch t1Waitt2 ;
        protected CountDownLatch t2Waitt1 ;

        public void setT1Waitt2(CountDownLatch t1Waitt2) {
            this.t1Waitt2 = t1Waitt2;
        }

        public void setT2Waitt1(CountDownLatch t2Waitt1) {
            this.t2Waitt1 = t2Waitt1;
        }

        public void setList(CountdownLatchArrayList list) {
            this.list = list;
        }

        public Abs(CountdownLatchArrayList list , CountDownLatch t1Waitt2 , CountDownLatch t2Waitt1){
            this.list = list ;
            this.t1Waitt2 = t1Waitt2 ;
            this.t2Waitt1 = t2Waitt1 ;
        }
    }
}
